home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d20
/
msgq160s.arc
/
EDITMAIL.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-10-26
|
26KB
|
1,312 lines
/*
* EDITMAIL.C - Message editing
*
* Msged/Q message editor for QuickBBS Copyright 1990 by P.J. Muller
*
*/
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "msged.h"
#include "screen.h"
#define EDITMAIL
#include "editmail.h"
#include "shell.h"
#include <assert.h> /* special */
void putl(LINE *l);
#define clearline(l,c) memset(l,0,c)
#define BUFLEN 256
static int down1(int y);
static int wrap(LINE *cl,char *r,int y);
static void reformat(LINE *cl);
static void insert_char(char c);
static void wrapline(void);
static int done = FALSE;
static int insert = ON;
static int x = 1, y = 1;
static char line[BUFLEN];
static LINE *current = NULL;
static LINE *first = NULL;
static LINE *last = NULL;
static LINE *pastebuf = NULL;
static int changed = 0;
static int direction = 0;
static int noteflag;
LINE *anchorpt = NULL;
extern LINE *top;
extern LINE *bottom;
int editmsg(void);
void putl(LINE *l)
{
if (l->block)
set_color(co_block);
else if (l->hide)
set_color(co_info);
else if (l->quote)
set_color(co_quote);
else
set_color(co_normal);
#ifdef ZAPTHISOUT
{ char *s;
for (s=l->text; *s != EOS; s++)
if (*s == ' ') bputc(250); else bputc(*s);
}
#else
bputs(l->text);
#endif
if (techie && (strchr(l->text,'\n') != NULL)) {
set_color(co_info);
bputc((char)20); /* paragraph mark */
} /* if */
set_color(co_normal);
}
int dorot13(int c)
{
switch (rot13) {
case 1:
c &= 0x7F;
if (!isalpha(c))
return(c);
if (((c >= 'A') && (c <= 'M')) || ((c >= 'a') && (c <= 'm')))
return(c + 0xd);
if (((c >= 'N') && (c <= 'Z')) || ((c >= 'n') && (c <= 'z')))
return(c - 0xd);
break;
case 2:
return (c >= '!') ? (((c + 47) > '~') ? (c - 47) : (c + 47)) : c;
case 3:
return tolower(c);
}
return(c);
}
void go_bol()
{
x = 1;
}
static int down1(int y)
{
if (++y > (maxy - 6)) {
y = maxy - 6;
scrollup(1, 7, maxx, maxy, 1);
}
gotoxy(1, y + 6);
return (y);
}
static int wrap(LINE *cl,char *r,int y)
{
char *l = NULL;
char *s = NULL;
LINE *nl = NULL;
int i = 0;
int j = 0;
int x2 = 0;
if (cl == NULL)
return(x);
if (r != NULL)
j = i = strlen(r);
if (cl->text != NULL)
i += strlen(cl->text);
if (i != 0)
l = (char *) calloc(1,i+5);
if (r != NULL) {
strcpy(l,r);
ptrfree(r);
}
if (cl->text != NULL) {
strcat(l,cl->text);
ptrfree(cl->text);
cl->text = NULL;
}
x2 = strlen(l);
if (x2 < rm) {
cl->text = l;
if ((y + 6) <= maxy) {
gotoxy(1,y + 6);
clreol();
putl(cl);
}
return(x);
}
s = l + rm;
while (isspace(*s))
s--;
while (!isspace(*s) && (s > l))
s--;
if (s <= l) {
s = l + rm;
while (!ispunct(*s) && (s > l))
s--;
}
if (s <= l)
s = l + rm - 1;
else
s++;
r = strdup(s);
assert(r);
*s = '\0';
if ((x + l) > (s - j))
x2 = (x + j) - (int)(s - l);
else
x2 = x;
cl->text = (char *) realloc(l,strlen(l)+1);
if ((y + 6) <= maxy) {
gotoxy(1,y + 6);
clreol();
putl(cl);
y++;
}
if (strchr(r,'\n') != NULL) {
if ((y+6) <= maxy) {
if ((y+6) < maxy)
scrolldown(1,y+6,maxx,maxy,1);
gotoxy(1,y+6);
clreol();
bputs(r);
}
nl = (LINE *) calloc(1,sizeof(LINE));
assert(nl);
nl->next = cl->next;
if (cl->next != NULL)
cl->next->prev = nl;
else
last = nl;
nl->prev = cl;
cl->next = nl;
nl->text = r;
return(x2);
}
if (cl->next == NULL) {
cl->next = (LINE *) calloc(1,sizeof(LINE));
assert(cl->next);
cl->next->prev = cl;
cl->next->text = NULL;
last = cl->next;
}
assert(cl->next);
wrap(cl->next,r,y);
return(x2);
}
void insert_char(char c)
{
strins(line, c, x);
if (strlen(line) > rm) {
wrapline();
return;
}
gotoxy(x, y + 6);
clreol();
assert(line + x - 1);
if (current->block)
set_color(co_block);
else if (current->hide)
set_color(co_warn);
else if (current->quote)
set_color(co_quote);
else
set_color(co_normal);
bputs((line + x - 1));
set_color(co_normal);
x++;
}
void delete_character()
{
LINE *l;
char *t,*s;
if (current->text != NULL)
ptrfree(current->text);
current->text = strdup(line);
assert(current->text);
changed = TRUE;
if ((*(line + x) == '\0') && (current->next != NULL)) {
t = current->text;
s = strchr(t,'\n');
if (s != NULL)
*s = '\0';
current->text = current->next->text;
l = current->next;
if (current->next->next != NULL)
current->next->next->prev = current;
current->next = current->next->next;
ptrfree(l);
if ((y+6) < maxy)
scrollup(1,(y+6),maxx,maxy,1);
wrap(current,t,y);
clearline(line,BUFLEN);
if (current->text != NULL)
strcpy(line,current->text);
return;
}
strdel(line, x);
clreol();
assert(line + x - 1);
if (current->block)
set_color(co_block);
else if (current->hide)
set_color(co_warn);
else if (current->quote)
set_color(co_quote);
else
set_color(co_normal);
bputs((line + x - 1));
}
void backspace()
{
changed = TRUE;
if (x == 1) {
go_up();
go_eol();
delete_character();
return;
}
strdel(line, --x);
gotoxy(x, y + 6);
clreol();
assert(line + x - 1);
if (current->block)
set_color(co_block);
else if (current->hide)
set_color(co_warn);
else if (current->quote)
set_color(co_quote);
else
set_color(co_normal);
bputs((line + x - 1));
}
void wrapline()
{
int x2;
if (changed) {
if (current->text != NULL)
ptrfree(current->text);
current->text = strdup(line);
assert(current->text);
changed = FALSE;
}
x2 = wrap(current,NULL,y);
if (x2 != x) {
current = current->next;
x = x2;
y = down1(y);
gotoxy(1,y+6);
clreol();
putl(current);
}
x++;
clearline(line,BUFLEN);
if (current->text != NULL)
strcpy(line,current->text);
}
void go_eol()
{
x = strlen(line);
if (*(line + x - 1) != '\n')
x++;
x = max(1, x);
}
void go_up()
{
if (current->prev == NULL)
return;
if (changed) {
if (current->text != NULL)
ptrfree(current->text);
current->text = strdup(line);
assert(current->text);
changed = FALSE;
}
if (y == 1)
scrolldown(1, y + 6, maxx, maxy, 1);
else
y--;
current = current->prev;
#if 0
if ((current != anchorpt) && (anchorpt != NULL))
current->block ^= 1;
#endif
direction = UP;
assert(current);
clearline(line, BUFLEN);
if (current->text != NULL)
strcpy(line, current->text);
if (x > strlen(line))
go_eol();
gotoxy(1, y + 6);
putl(current);
}
void go_down()
{
if (current->next == NULL)
return;
if (changed) {
if (current->text != NULL)
ptrfree(current->text);
current->text = strdup(line);
assert(current->text);
changed = FALSE;
}
direction = DOWN;
if (y > (maxy - 7))
scrollup(1, 7, maxx, maxy, 1);
else
y++;
current = current->next;
#if 0
if ((current != anchorpt) && (anchorpt != NULL))
current->block ^= 1;
#endif
assert(current);
clearline(line, BUFLEN);
if (current->text != NULL)
strcpy(line, current->text);
if (x > strlen(line))
go_eol();
gotoxy(1, y + 6);
putl(current);
x = max(1, x);
}
void go_left()
{
if (x == 1) {
if (current->prev != NULL) {
go_up();
go_eol();
}
return;
}
x--;
}
void go_right()
{
if (*(line + x - 1) == '\0') {
if (current->next != NULL) {
go_down();
x = 1;
}
return;
}
if (*(line + x - 1) == '\n') {
if (current->next != NULL) {
go_down();
x = 1;
}
return;
}
x++;
}
void go_word_right()
{
if (*(line + x - 1) == '\0') {
if (current->next != NULL) {
go_down();
x = 1;
}
return;
}
if (*(line + x - 1) == '\n') {
if (current->next != NULL) {
go_down();
x = 1;
}
return;
}
while (isspace(*(line + x - 1)) && (x <= strlen(line)))
x++;
while (!isspace(*(line + x - 1)) && (x <= strlen(line)))
x++;
while (isspace(*(line + x - 1)) && (x <= strlen(line)))
x++;
if (*(line + x - 2) == '\n')
x--;
}
void go_word_left()
{
if (x == 1) {
if (current->prev != NULL) {
go_up();
go_eol();
}
return;
}
while (isspace(*(line + x - 1)) && (x > 1))
x--;
while (!isspace(*(line + x - 1)) && (x > 1))
x--;
while (isspace(*(line + x - 1)) && (x > 1))
x--;
while (!isspace(*(line + x - 1)) && (x > 1))
x--;
if (x != 1)
x++;
}
void newline()
{
char l[BUFLEN];
char *t = line + x - 1;
int inblock = FALSE;
changed = FALSE;
if (current->text != NULL)
ptrfree(current->text);
clearline(l, BUFLEN);
strncpy(l, line, x - 1);
strcat(l, "\n");
current->text = strdup(l);
#if 0
inblock = current->block;
#endif
assert(current->text);
clreol();
x = 1;
y = down1(y);
gotoxy(x, y + 6);
if (current->next == NULL) {
if ((current->next = (LINE *) calloc(1, sizeof(LINE))) == NULL)
return;
current->next->text = strdup(t);
current->next->block = inblock;
assert(current->next->text);
current->next->next = NULL;
current->next->prev = current;
current = current->next;
last = current;
assert(current->text);
putl(current);
msgbuf.first = first;
msgbuf.last = last;
clearline(line, BUFLEN);
if (current->text != NULL)
strcpy(line, current->text);
return;
}
if (strchr(t, '\n') != NULL) {
LINE *nl;
if ((nl = (LINE *) calloc(1, sizeof(LINE))) == NULL)
return;
nl->text = strdup(t);
nl->block = inblock;
assert(nl->text);
nl->next = current->next;
nl->next->prev = nl;
current->next = nl;
nl->prev = current;
current = nl;
if ((y + 6) < maxy)
scrolldown(1, y + 6, maxx, maxy, 1);
gotoxy(1, y + 6);
clreol();
assert(current->text);
putl(current);
msgbuf.first = first;
msgbuf.last = last;
clearline(line, BUFLEN);
if (current->text != NULL)
strcpy(line, current->text);
return;
}
clearline(l, BUFLEN);
strcpy(l, t);
assert(current->next);
current = current->next;
if (current->text) {
strcat(l, current->text);
ptrfree(current->text);
current->text = NULL;
}
clearline(line, BUFLEN);
x = 0;
changed = TRUE;
strcpy(line, l);
wrapline();
}
void go_pgup()
{
int count = y - 1;
LINE *l = current;
/* LINE *t = current; */
if (changed) {
if (current->text != NULL)
ptrfree(current->text);
current->text = strdup(line);
assert(current->text);
clearline(line,sizeof(line));
changed = FALSE;
}
while (count-- && current->prev) {
current = current->prev;
}
count = maxy - 7;
while (count-- && current->prev) {
current = current->prev;
}
if (l != current) {
y = 1;
l = current;
count = 0;
clrwnd(1,7,maxx,maxy);
while (((count + 7) < maxy) && (l->next)) {
#if 0
if ((l != anchorpt) && (anchorpt != NULL))
l->block ^= 1;
#endif
gotoxy(1,count++ + 7);
putl(l);
l = l->next;
}
gotoxy(1,count + 7);
putl(l);
}
if (current->text != NULL)
strcpy(line,current->text);
}
void go_pgdown()
{
int count = maxy - 7;
LINE *l = current;
if (changed) {
if (current->text != NULL)
ptrfree(current->text);
current->text = strdup(line);
assert(current->text);
changed = FALSE;
clearline(line,sizeof(line));
}
while (count-- && current->next) {
current = current->next;
}
if (l != current) {
count = 0;
l = current;
clrwnd(1,7,maxx,maxy);
while (((count + 7) < maxy) && l->next) {
#if 0
if ((l != anchorpt) && (anchorpt != NULL))
l->block ^= 1;
#endif
gotoxy(1,++count + 6);
putl(l);
l = l->next;
}
gotoxy(1,++count + 6);
putl(l);
}
y = 1;
if (current->text != NULL)
strcpy(line,current->text);
}
void delete_line()
{
LINE *t = current;
LINE *l = current;
int y2;
changed = FALSE;
if (current->next == NULL) {
msgbuf.last = current->prev; /* deleting last line */
if (current->text != NULL)
ptrfree(current->text);
current->text = NULL;
gotoxy(x=1,y+6);
clearline(line,sizeof(line));
clreol();
return;
}
if ((y+6) < maxy)
scrollup(1, y + 6, maxx, maxy, 1);
else
scrollup(1,maxy,maxx,maxy,0);
t = current;
clearline(line, BUFLEN);
assert(current);
if (current->next == NULL) {
if (current->text != NULL)
ptrfree(current->text);
assert(current);
current->text = NULL;
if (current->prev != NULL) {
current = current->prev;
ptrfree(current->next);
current->next = NULL;
y--;
if (y < 1) {
y = 1;
clreol();
}
gotoxy(1,y + 6);
clearline(line,sizeof(line));
if (current->text != NULL)
strcpy(line,current->text);
putl(current);
x = min(x,strlen(line));
}
else {
first = current;
x = y = 1;
}
msgbuf.first = first;
msgbuf.last = last = current;
current->next = NULL;
return;
}
assert(current->next);
if (current->prev != NULL) { /* first line? */
current->next->prev = current->prev; /* no */
current->prev->next = current->next;
}
else {
current->next->prev = NULL; /* yes */
first = current->next;
}
current = current->next;
msgbuf.first = first;
msgbuf.last = last;
if (t->text != NULL)
ptrfree(t->text);
t->text = NULL;
ptrfree(t);
t = NULL;
if (current->text != NULL)
strcpy(line, current->text);
else
clearline(line,sizeof(line));
if (x > strlen(line))
go_eol();
l = current; y2 = y;
while (((y2 + 6) < maxy) && l->next && l->next->text) {
y2++;
l = l->next;
}
gotoxy(1,y2 + 6);
putl(l);
x = max(1,x);
}
void anchor()
{
if (anchorpt != NULL) {
set_color(co_normal);
refresh(current,y=1);
anchorpt->block = 0;
anchorpt->column = 0;
anchorpt = NULL;
while (pastebuf) {
ptrfree(pastebuf->text);
if (pastebuf->next) {
pastebuf = pastebuf->next;
ptrfree(pastebuf->prev);
}
else {
ptrfree(pastebuf);
pastebuf = NULL;
}
}
}
anchorpt = current;
current->column = x;
current->block = 1;
gotoxy(1,y+6);
putl(current);
}
void cut()
{
LINE *f = current;
LINE *l = current;
if (changed) {
if (current->text != NULL)
ptrfree(current->text);
current->text = strdup(line);
assert(current->text);
}
while (l->next && (l != anchorpt))
l = l->next;
if (l != anchorpt) {
l = current;
while (f->prev && (f != anchorpt))
f = f->prev;
if (f != anchorpt)
return;
}
if (f->prev == NULL)
first = l->next;
else
f->prev->next = l->next;
if (l->next == NULL)
last = f->prev;
else
l->next->prev = f->prev;
if (l->next != NULL)
current = l->next;
else
current = f->prev;
l->next = NULL;
f->prev = NULL;
if ((first == NULL) && (last == NULL))
first = last = current = (LINE *) calloc(1,sizeof(LINE));
pastebuf = f;
clearline(line,sizeof(line));
if (current->text != NULL)
strcpy(line,current->text);
refresh(current,1);
y = x = 1;
}
void paste()
{
LINE *l = pastebuf;
LINE *t,*s = NULL;
LINE *t1 = current->prev;
if (l == NULL)
return;
if (changed) {
if (current->text != NULL)
ptrfree(current->text);
current->text = strdup(line);
assert(current->text);
}
while (l) {
t = (LINE *) calloc(1,sizeof(LINE));
if (s == NULL)
s = t;
current->prev = t;
t->next = current;
t->prev = t1;
if (t1 == NULL)
first = t;
else
t1->next = t;
t->text = strdup(l->text);
l = l->next;
t1 = t;
}
current = s;
if (current->text != NULL)
strcpy(line,current->text);
refresh(current,1);
y = x = 1;
}
static void reformat(LINE *cl)
{
char *t;
LINE *l = cl->next;
int y2 = y;
if (cl->next == NULL)
return;
while ((cl->next->next != NULL) & (strchr(cl->text,'\n') == NULL)) {
t = cl->text;
cl->text = cl->next->text;
cl->next->next->prev = cl;
cl->next = cl->next->next;
ptrfree(l);
wrap(cl,t,y2);
if (cl->next == NULL)
return;
cl = cl->next;
y2++;
}
}
void quit()
{
anchorpt = NULL;
set_color(co_normal);
shownotes = noteflag;
if (changed) {
if (current->text) {
if ((current->text = realloc(current->text,strlen(line)+1)) == NULL) {
gotoxy(9,1);
clreol();
set_color(co_warn);
bputs("*warning* ");
bputs("memory error! message truncated, press a key");
getkey();
set_color(co_normal);
}
memset(current->text,0,strlen(line)+1);
strcpy(current->text, line);
}
else {
current->text = strdup(line);
assert(current->text);
}
}
if (first == NULL)
first = last = current;
msgbuf.first = first;
if (last->next != NULL)
msgbuf.last = last->next;
else
msgbuf.last = last;
done = SAVE;
}
void die()
{
if (!confirm(confirmations))
showheader(message);
else
done = ABORT;
}
void imptxt()
{
msgbuf.last = last;
msgbuf.first = first;
if (current->text != NULL)
ptrfree(current->text);
if (strlen(line) > 0) {
current->text = strdup(line);
assert(current->text);
}
else
current->text = NULL;
import(current);
showheader(message);
first = msgbuf.first;
last = msgbuf.last;
refresh(current, 1);
x = y = 1;
if (current->text != NULL)
strcpy(line, current->text);
else
clearline(line,sizeof(line));
}
void outtext()
{
if (pastebuf != NULL)
export(pastebuf);
else if (anchorpt != NULL)
export(anchorpt);
else if (current != NULL)
export(current);
}
void shellos()
{
#ifndef MINI
if (changed) {
if (current->text != NULL)
ptrfree(current->text);
current->text = strdup(line);
assert(current->text);
}
os();
showheader(message);
x = y = 1;
refresh(current, 1);
#endif
}
void helped()
{
if (changed) {
if (current->text != NULL)
ptrfree(current->text);
current->text = strdup(line);
assert(current->text);
}
helpedit();
showheader(message);
x = y = 1;
refresh(current, 1);
} /* helped */
void format()
{
if (changed) {
if (current->text)
ptrfree(current->text);
current->text = strdup(line);
assert(current->text);
}
reformat(current);
clearline(line,BUFLEN);
if (current->text)
strcpy(line,current->text);
x = 1;
}
void toggle_ins()
{
insert = !insert;
if (insert) {
set_color(co_info);
gotoxy((maxx - 4), 5);
bputs("ins");
}
else {
gotoxy((maxx - 4), 5);
bputs(" ");
}
set_color(co_normal);
}
void tabit()
{
changed = TRUE;
if (!(x%tabsize))
insert_char(' ');
while (x % tabsize)
insert_char(' ');
insert_char(' ');
}
void go_tos()
{
int count = y - 1;
if (changed) {
if (current->text != NULL)
ptrfree(current->text);
current->text = strdup(line);
assert(current->text);
changed = FALSE;
}
while (count-- && current->prev) {
current = current->prev;
}
x = y = 1;
clearline(line,sizeof(line));
if (current->text != NULL)
strcpy(line,current->text);
}
void go_bos()
{
if (changed) {
if (current->text != NULL)
ptrfree(current->text);
current->text = strdup(line);
assert(current->text);
changed = FALSE;
}
while (((y + 6) < maxy) && current->next) {
current = current->next;
y++;
}
x = 1;
clearline(line,sizeof(line));
if (current->text != NULL)
strcpy(line,current->text);
}
void go_tom()
{
if (changed) {
if (current->text != NULL)
ptrfree(current->text);
current->text = strdup(line);
assert(current->text);
changed = FALSE;
}
current = first;
clearline(line,sizeof(line));
if (current->text != NULL)
strcpy(line,current->text);
refresh(current,1);
x = y = 1;
}
void go_bom()
{
if (changed) {
if (current->text != NULL)
ptrfree(current->text);
current->text = strdup(line);
assert(current->text);
changed = FALSE;
}
current = last;
x = y = 1;
clearline(line,sizeof(line));
if (current->text != NULL)
strcpy(line,current->text);
if (current->prev) {
refresh(current->prev,1);
y = 2;
}
else
refresh(current,1);
}
void killeol()
{
char *s;
if (strchr(line,'\n') == NULL)
*(s = (line + x - 1)) = '\0';
else {
*(line + x - 1) = '\n';
*(s = (line + x)) = '\0';
}
memset(s,0,sizeof line - (int)(s - line) - 1);
changed = TRUE;
clreol();
}
int editmsg()
{
unsigned int ch;
#ifdef EXTERNEDIT
if (!writebuffile("$msgedq.tmp", &msgbuf))
return ABORT;
if (!shell("LS.COM", "$msgedq.tmp"))
return ABORT;
if (readbuffile("$msgedq.tmp", &msgbuf))
return SAVE;
else
return ABORT;
#endif
noteflag = shownotes;
anchorpt = NULL;
shownotes = TRUE;
x = y = 1;
current = first = msgbuf.first;
last = msgbuf.last;
clearline(line, BUFLEN);
if (insert) {
set_color(co_info);
gotoxy((maxx-4), 5);
bputs("ins");
set_color(co_normal);
}
if (first == NULL) {
if ((first = (LINE *) calloc(1, sizeof(LINE))) == NULL) {
gotoxy(9,1);
clreol();
set_color(co_warn);
bputs("*warning* ");
bputs("ran out of memory! press a key");
getkey();
set_color(co_normal);
return(ABORT);
}
first->text = NULL;
first->prev = NULL;
last = current = first;
}
else if (current->text != NULL)
strcpy(line, current->text);
else
clearline(line,sizeof(line));
refresh(current, 1);
gotoxy(1, 7);
done = FALSE;
while (!done) {
gotoxy(x,y+6);
video_update();
ch = getkey();
if (ch & 0xff) {
if (editckeys[(ch & 0xff)] == NULL) {
changed = TRUE;
if (insert)
insert_char((char) (ch & 0xff));
else {
delete_character();
insert_char((char) (ch & 0xff));
}
}
else
editckeys[(ch & 0xff)]();
}
else if (editakeys[(ch >> 8)] != NULL)
editakeys[(ch >> 8)]();
else
continue;
}
shownotes = noteflag;
return(done);
}